/*
 * Copyright (c) 2020 hebeiyiliuba.com
 * All rights reserved.
 *
 */
package org.jeecg.common.util;

import org.apache.commons.lang.StringUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

/**
 * 校验银行卡卡号
 *
 * @author duanlikao
 * @created 2021/1/21
 */
public class CheckBankCardIUtil {

    private static Map<String, String> bankMaps = new HashMap<String, String>(){{
        put("BKCH","中国银行");
        put("ABOC","农业银行");
        put("ICBK","工商银行");
        put("PCBC","建设银行");
        put("PSBC","邮政储蓄");
        put("COMM","交通银行");
        put("CMBC","招商银行");
        put("SZDB","平安银行");
        put("CIBK","中信银行");
        put("MSBC","民生银行");
        put("GDBK","广发银行");
        put("SPDB","浦发银行");
        put("FJIB","兴业银行");
        put("EVER","光大银行");
        put("ZJCB","浙商银行");
        put("CTBA","澳大利亚联邦银行");
        put("ANBK","鞍山银行");
        put("ANZB","澳新银行");
        put("NOLA","北德意志州银行");
        put("CHBH","渤海银行");
        put("BRCB","北京农村商业银行");
        put("BJCN","北京银行");
        put("BARC","巴克莱银行");
        put("BARB","巴罗达银行");
        put("KRED","比利时联合银行");
        put("BTCB","包商银行");
        put("CDRC","成都农村商业银行");
        put("CBOC","成都银行");
        put("CSCB","常熟农村商业银行");
        put("DDBK","丹东银行");
        put("CRLY","东方汇理银行");
        put("DGCB","东莞银行");
        put("UOVB","大华银行");
        put("DLCB","大连银行");
        put("DSBA","大新银行");
        put("DECC","德阳银行");
        put("BEAS","东亚银行");
        put("DYSH","东营银行");
        put("DEUT","德意志银行");
        put("FSBC","富邦华一银行");
        put("KCCB","富滇银行");
        put("BNPA","法国巴黎银行");
        put("NATX","法国外贸银行");
        put("SGCL","法国兴业银行");
        put("PNBP","富国银行");
        put("FZCB","福建海峡银行");
        put("FXBK","阜新银行");
        put("GDHB","广东华兴银行");
        put("RCNH","广东南海农村商业银行");
        put("RCCS","广东顺德农村商业银行");
        put("SDBC","国家开发银行");
        put("GLBK","桂林银行");
        put("CZNB","国民银行");
        put("BGBK","广西北部湾银行");
        put("GYCB","贵阳银行");
        put("GZRC","广州农村商业银行");
        put("BKGZ","赣州银行");
        put("GZCB","广州银行");
        put("BKSH","河北银行");
        put("BKHD","邯郸银行");
        put("HCCB","哈尔滨银行");
        put("HSBC","汇丰银行");
        put("KODB","韩国产业银行");
        put("SHBK","韩国新韩银行");
        put("WHCB","汉口银行");
        put("INGB","荷兰安智银行");
        put("RABO","荷兰合作银行");
        put("DRCB","黑龙江东宁农村商业银行");
        put("EWBK","华美银行");
        put("CITI","花旗银行");
        put("OCBC","华侨银行");
        put("HASE","恒生银行");
        put("CNMB","华商银行");
        put("HXBK","华夏银行");
        put("HNBN","韩亚银行");
        put("HRCN","惠州农村商业银行");
        put("HZCB","杭州银行");
        put("JHCB","金华银行");
        put("BOJJ","九江银行");
        put("HCRR","吉林珲村农村商业银行");
        put("JTCB","吉林九台农村商业银行");
        put("JLBK","吉林银行");
        put("NOSC","加拿大丰业银行");
        put("ROYC","加拿大皇家银行");
        put("BKJN","济宁银行");
        put("DYCB","江苏丹阳农村商业银行");
        put("HRCB","江苏海安农村商业银行");
        put("HMCB","江苏海门农村商业银行");
        put("RCWJ","江苏靖江农村商业银行");
        put("JYCB","江苏江阴农村商业银行");
        put("JRCB","江苏姜堰农村商业银行");
        put("NRCB","江苏南通农村商业银行");
        put("PZCB","江苏邳州农村商业银行");
        put("RRCB","江苏如东农村商业银行");
        put("RGCB","江苏如皋农村商业银行");
        put("JSCB","江苏射阳农村商业银行");
        put("WJRB","江苏吴江农村商业银行");
        put("JYHR","江苏盐城黄海农村商业银行");
        put("BOJS","江苏银行");
        put("JSHB","晋商银行");
        put("URCC","江苏宜兴农村商业银行");
        put("YZRC","江苏扬州农村商业银行");
        put("JRZC","江苏紫金农村商业银行");
        put("BOJX","嘉兴银行");
        put("CIYU","集友银行");
        put("JZCB","锦州银行");
        put("CKLB","昆仑银行");
        put("BOLF","廊坊银行");
        put("LJBC","龙江银行");
        put("LSCC","乐山市商业银行");
        put("LWCB","莱商银行");
        put("LYCB","临商银行");
        put("LCOM","辽阳银行");
        put("BOLY","洛阳银行");
        put("LZCB","兰州银行");
        put("LZBK","柳州银行");
        put("CHAS","摩根大通银行");
        put("BOFO","美国建东银行");
        put("MSBK","摩根士丹利国际银行");
        put("NAGO","民古屋银行");
        put("BOFA","美国银行");
        put("MBBE","马来亚银行");
        put("BOFM","蒙特利尔银行");
        put("DHBC","宁波东海银行");
        put("BINH","宁波通商银行");
        put("BKNB","宁波银行");
        put("NCCC","南充市商业银行");
        put("NCCK","南昌银行");
        put("NJCB","南京银行");
        put("HSSY","内蒙古银行");
        put("YCCB","宁夏银行");
        put("NYCB","南洋商业银行");
        put("BNYM","纽约银行");
        put("SSVB","浦发硅谷银行");
        put("BKKB","盘谷银行");
        put("QDRC","青岛农村商业银行");
        put("QCCB","青岛银行");
        put("BOXN","青海银行");
        put("JNSH","齐鲁银行");
        put("ZBBK","齐商银行");
        put("IBKO","企业银行");
        put("QRCB","泉州农村商业银行");
        put("BKQZ","泉州银行");
        put("ESSE","瑞典北欧斯安银行");
        put("CRES","瑞士信贷银行");
        put("UBSW","瑞士银行");
        put("MHCB","瑞穗银行");
        put("RZCB","日照银行");
        put("SGRB","山东寿光农村商业银行");
        put("MBTC","首都银行");
        put("ZDRB","山东张店农村商业银行");
        put("ABNA","苏格兰皇家银行");
        put("SHRC","上海农村商业银行");
        put("BOSH","上海银行");
        put("SYCB","盛京银行");
        put("SMBC","三井住友银行");
        put("BOTK","三菱东京日联银行");
        put("IBXH","厦门国际银行");
        put("RCXM","厦门农村商业银行");
        put("CBXM","厦门银行");
        put("YDBK","陕西药都农村商业银行");
        put("SXCB","绍兴银行");
        put("SRCC","深圳农村商业银行");
        put("BHRC","天津滨海农村商业银行");
        put("TJRC","天津农村商业银行");
        put("TCCB","天津银行");
        put("BOTS","唐山市商业银行");
        put("TZBK","台州银行");
        put("WRCB","潍坊农村商业银行");
        put("WFCB","潍坊银行");
        put("WRCC","武汉农村商业银行");
        put("KOEX","外换银行");
        put("WHBK","威海银行");
        put("UCCB","乌鲁木齐商业银行");
        put("HFCB","徽商银行");
        put("WZCB","温州银行");
        put("IXAB","西安银行");
        put("CBNB","协和银行");
        put("DBSS","新加坡发展银行");
        put("COXI","新联商业银行");
        put("WPAC","西太平洋银行");
        put("YBRC","延边农村商业银行");
        put("BCIT","意大利联合圣保罗银行");
        put("BROM","意大利联合信贷");
        put("WIHB","永亨银行");
        put("YKCB","营口银行");
        put("HVBK","友利银行");
        put("ZFRB","烟台农村商业银行");
        put("CRCK","长春农村商业银行");
        put("SCBL","渣打银行");
        put("ICBC","兆丰国际商业银行");
        put("EIBC","中国进出口银行");
        put("ADBN","中国农业发展银行");
        put("CTCB","中国信托银行");
        put("ZRCB","珠海农村商业银行");
        put("CZCB","浙江稠州银行");
        put("HCRC","浙江禾城农村商业银行");
        put("YHBK","浙江杭州余杭农村商业银行");
        put("ZJMT","浙江民泰商业银行");
        put("ZJTL","浙江泰隆商业银行");
        put("LCBK","浙江温州鹿城农村商业银行");
        put("ZXBK","浙江新昌农村商业银行");
        put("YWBK","浙江义乌农村商业银行");
        put("ZJRB","浙江诸暨农村商业银行");
        put("ZJPT","浙江舟山普陀农村商业银行");
        put("CQRB","重庆农村商业银行");
        put("CTGB","重庆三峡银行");
        put("CQCB","重庆银行");
        put("CHCC","长沙银行");
        put("ZXBC","正信银行");
        put("ZZBK","郑州银行");
        put("WEBANK","深圳前海微众银行");
        put("MSBANK","温州民商银行");
        put("KCBANK","天津金城银行");
        put("MYBANK","浙江网商银行");
        put("SHRB","上海华瑞银行");
        put("FMBANK","重庆富民银行");
        put("XWBANK","四川新网银行");
        put("SXBANK","湖南三湘银行");
        put("XABANK","安徽新安银行");
        put("ONEBANK","福建华通银行");
        put("ZBANK","武汉众邦银行");
        put("ZGCBANK","北京中关村银行");
        put("SNBANK","江苏苏宁银行");
        put("BOBANK","威海蓝海银行");
        put("NUBANK","辽宁振兴银行");
        put("YLBANK","吉林亿联银行");
        put("HBRCB","河北省农村信用社联合社");
        put("SXRCB","山西省农村信用社联合社");
        put("FDBANK","富滇银行");
        put("YNCB","云南农村商业银行");
        put("JNCB","江南农村商业银行");
        put("XZCB","徐州农村商业银行");
        put("RCC","内乡县农村信用合作联社");
    }};


    /**
     * 校验过程：
     *     1、从卡号最后一位数字开始，逆向将奇数位(1、3、5等等)相加。
     *     2、从卡号最后一位数字开始，逆向将偶数位数字，先乘以2（如果乘积为两位数，将个位十位数字相加，即将其减去9），再求和。
     *     3、将奇数位总和加上偶数位总和，结果应该可以被10整除。
     * 校验银行卡卡号
     */
    public static boolean checkBankCard(String bankCard) {
        if(bankCard.length() < 15 || bankCard.length() > 19) {
            return false;
        }
        char bit = getBankCardCheckCode(bankCard.substring(0, bankCard.length() - 1));
        if(bit == 'N'){
            return false;
        }
        return bankCard.charAt(bankCard.length() - 1) == bit;
    }

    /**
     * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
     * @param nonCheckCodeBankCard
     * @return
     */
    public static char getBankCardCheckCode(String nonCheckCodeBankCard){
        if(nonCheckCodeBankCard == null || nonCheckCodeBankCard.trim().length() == 0
                || !nonCheckCodeBankCard.matches("\\d+")) {
            //如果传的不是数据返回N
            return 'N';
        }
        char[] chs = nonCheckCodeBankCard.trim().toCharArray();
        int luhmSum = 0;
        for(int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if(j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return (luhmSum % 10 == 0) ? '0' : (char)((10 - luhmSum % 10) + '0');
    }

    public static String getCardDetail(String cardNo) {
        cardNo = cardNo.replaceAll(" ","");
        if(StringUtils.isEmpty(cardNo)){
            return null;
        }
        // 创建HttpClient实例
        String url = "https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?_input_charset=utf-8&cardNo=";
        url+=cardNo;
        url+="&cardBinCheck=true";
        StringBuilder sb = new StringBuilder();
        try {
            URL urlObject = new URL(url);
            URLConnection uc = urlObject.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
            String inputLine = null;
            while ( (inputLine = in.readLine()) != null) {
                sb.append(inputLine);
            }
            in.close();
        }catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        return sb.toString();
    }

    public static String getBankNameByBankCode(String bankCode){
        String name = bankMaps.get(bankCode);
        return name;
    }

}
